--[[
	Copyright (C) Udorn (Blackhand)
--]]

local viewType = "Window"
local version = 1
local YakaGui = LibStub("YakaGui", true)
local info = YakaGui:GetViewInfo(viewType) 
if (info and info.version >= version) then 
	return 
end

yaka = yaka or {}
yaka.Window = {}
yaka.Window.prototype = {}
yaka.Window.metatable = {__index = yaka.Window.prototype}
setmetatable(yaka.Window.prototype, {__index = yaka.Container.prototype})

yaka.Window.info = {viewType = viewType, version = version}
yaka.Window.GetViewInfo = function()
	return yaka.Window.info
end

local log = vendor.Debug:new("Window")

local function _OnUpdate(info, this, elapsed)
	local self = this.view
	if (self.requestLayout) then
		if (self.lastLayout) then
			if (self.waitLayout) then
				self.waitLayout = self.waitLayout + elapsed
			else
				self.waitLayout = self.lastLayout
			end	
			if (self.waitLayout > self.lastLayout + 0.2) then
				self.waitLayout = nil
				self.lastLayout = nil
			end
		end
		if (not self.lastLayout) then
			self.requestLayout = nil
			self:RequestLayout()
			self.lastLayout = GetTime()
		end
	end
end

local function _SaveWindow(self)
	if (self.cfg.saveTable) then
		local save = self.cfg.saveTable[self.cfg.name]
		if (not save) then
			self.cfg.saveTable[self.cfg.name] = {}
			save = self.cfg.saveTable[self.cfg.name]
		end
		save.width = self.frame:GetWidth()
		save.height = self.frame:GetHeight()
		local point, relativeTo, relativePoint, x, y = self.frame:GetPoint(1)
		save.point = point
		save.relativePoint = relativePoint
		save.x = math.floor(x + 0.5)
		save.y = math.floor(y + 0.5)
		log:Debug("SaveWindow width [%s] height [%s] point [%s] relativePoint [%s] x [%s] y [%s]", save.width, save.height, save.point, save.relativePoint, save.x, save.y)
	end
end

local function _LoadWindow(self, saveTable)
	local table = self.cfg.saveTable or saveTable
	if (table) then
		local save = table[self.cfg.name]
		if (save) then
			log:Debug("found width [%s] height [%s]", save.width, save.height)
			if (save.width) then
				self.frame:SetWidth(save.width)
			end
			if (save.height) then
				self.frame:SetHeight(save.height)
			end
			if (save.point) then
				log:Debug("found point [%s] relativePoint [%s] x [%s] y [%s]", save.point, save.relativePoint, save.x, save.y)
				self.frame:ClearAllPoints()
				self.frame:SetPoint(save.point, UIParent, save.relativePoint, save.x, save.y)
			end
		end
	end
end

local function _StopMovingOrSizing(frame)
	local self = frame.view
	frame:StopMovingOrSizing()
	_SaveWindow(self)
	self:RequestLayout()
end
 
local function _OnResizeMouseDown(this)
	this:SetButtonState("PUSHED", true)
	
	SetCursor("UI-Cursor-Size") -- hide the cursor
	this:GetHighlightTexture():Hide()
	
	this:GetParent():StartSizing(this.anchorPoint)
end

local function _OnResizeMouseUp(this)
	this:SetButtonState("NORMAL", false)
	SetCursor(nil) -- show the cursor again
	this:GetHighlightTexture():Show()
						
	_StopMovingOrSizing(this:GetParent())
end

local function _OnSizeChanged(this)
	local self = this.view
	self.requestLayout = true
	--self.layout:Layout(self.childs, self.frame:GetWidth(), self.frame:GetHeight())
	
	--_SaveWindow(self)
end

local function _CreateResize(frame, anchorPoint)
	local resize = CreateFrame("Button", nil, frame)
	resize:SetWidth(16)
	resize:SetHeight(16)
	resize.anchorPoint = anchorPoint
	--resize:EnableMouse()
	resize:SetScript("OnMouseDown", _OnResizeMouseDown)
	resize:SetScript("OnMouseUp", _OnResizeMouseUp)

	resize:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up")
	resize:SetHighlightTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Highlight")
	resize:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Down")
	
	return resize
end

--[[ 
	Creates a new instance.
--]]
function yaka.Window:new(cfg)
	local instance = setmetatable({}, self.metatable)
	instance:InitCfg(cfg)
	instance:InitFrame()	
	return instance
end

function yaka.Window.prototype:InitCfg(cfgIn)
	yaka.Container.prototype.InitCfg(self, cfgIn)
	
	if (not cfgIn.name) then
		error("can't create Window without name")
	end
	
	local cfg = self.cfg
	cfg.minWidth = cfgIn.minWidth or 100
	cfg.minHeight = cfgIn.minHeight or 100
	cfg.maxWidth = cfgIn.maxWidth or 2000
	cfg.maxHeight = cfgIn.maxHeight or 1000
	cfg.resizable = cfgIn.resizable or true
	cfg.moveable = cfgIn.moveable or true
	if (not cfg.backdrop) then
		cfg.backdrop = {bgFile = "Interface/Tooltips/UI-Tooltip-Background", 
                                            edgeFile = "Interface/Tooltips/UI-Tooltip-Border", 
                                            tile = true, tileSize = 16, edgeSize = 16, 
                                            insets = { left = 4, right = 4, top = 4, bottom = 4 }}
    end
    if (not cfg.backdropColor) then
    	cfg.backdropColor = {0, 0, 0, 1} 
    end
    self.saveTableIn = cfgIn.saveTable
end

function yaka.Window.prototype:InitFrame()
	yaka.Container.prototype.InitFrame(self)
	
	local frame = self.frame
	frame:EnableMouse(true)
	self:AddScript("OnUpdate", _OnUpdate)
	self:SetMoveable(self.cfg.moveable)
		
	-- resizing support
	local resizeBotRight = _CreateResize(frame, "BOTTOMRIGHT")
	resizeBotRight:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
	self.resizeBotRight = resizeBotRight

	local resizeBotLeft = _CreateResize(frame, "BOTTOMLEFT")
	resizeBotLeft:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 0)
	YakaGui:RotateTexture(resizeBotLeft:GetNormalTexture(), -90)
	YakaGui:RotateTexture(resizeBotLeft:GetHighlightTexture(), -90)
	YakaGui:RotateTexture(resizeBotLeft:GetPushedTexture(), -90)
	self.resizeBotLeft = resizeBotLeft

	self:SetResizeable(self.cfg.resizeable)
	
	log:Debug("saveTable [%s]", self.saveTableIn)
	_LoadWindow(self, self.saveTableIn)
	self.cfg.saveTable = self.saveTableIn -- we don't want to save before loading the window
	self.saveTableIn = nil
	
	local cfg = self.cfg

	-- TODO setters should not be needed
	self:SetMinDimension(cfg.minWidth, cfg.minHeight)
	self:SetMaxDimension(cfg.maxWidth, cfg.maxHeight)
	
	self:SetBackdrop(cfg.backdrop)
	self:SetBackdropColor(cfg.backdropColor)
	self:RequestLayout()
end

function yaka.Window.prototype:SetDimension(width, height)
	self.cfg.width = width
	self.cfg.height = height
	self.frame:SetWidth(width)
	self.frame:SetHeight(height)
end

function yaka.Window.prototype:SetMinDimension(width, height)
	self.cfg.minWidth = width
	self.cfg.minHeight = height
	self.frame:SetMinResize(width, height)
end

function yaka.Window.prototype:SetMaxDimension(width, height)
	self.cfg.maxWidth = width
	self.cfg.maxHeight = height
	self.frame:SetMaxResize(width, height)
end

function yaka.Window.prototype:SetBackdrop(backdrop)
	self.cfg.backdrop = backdrop
	self.frame:SetBackdrop(backdrop)
end

function yaka.Window.prototype:SetBackdropColor(colorArray)
	self.cfg.backdropColor = colorArray
	self.frame:SetBackdropColor(unpack(colorArray))
end	

function yaka.Window.prototype:SetBackdropBorderColor(colorArray)
	self.cfg.backdropBorderColor = colorArray
	self.frame:SetBackdropBorderColor(unpack(colorArray))
end	

function yaka.Window.prototype:SetMoveable(moveable)
	self.cfg.moveable = moveable 
	self.frame:SetMovable(self.cfg.moveable)
	if (self.cfg.moveable) then
    	self.frame:SetScript("OnMouseDown", function(this) this:StartMoving() end)
    	self.frame:SetScript("OnMouseUp", _StopMovingOrSizing)
    else
       	self.frame:SetScript("OnMouseDown", nil)
    	self.frame:SetScript("OnMouseUp", nil)
    end
end	

function yaka.Window.prototype:SetResizeable(resizeable)
	self.cfg.resizeable = resizeable
	self.frame:SetResizable(self.cfg.resizeable)
	if (self.cfg.resizeable) then
		self.frame:SetScript("OnSizeChanged", _OnSizeChanged)
		self.resizeBotRight:Show()
		self.resizeBotLeft:Show()
	else
		frame:SetScript("OnSizeChanged", nil)
		self.resizeBotRight:Hide()
		self.resizeBotLeft:Hide()
	end
end

function yaka.Window.prototype:RequestLayout()
	self.layout:Layout(self.childs, self.frame:GetWidth(), self.frame:GetHeight())
end

-- register view

YakaGui:RegisterViewType(yaka.Window)